﻿using System;
using System.IO;
using System.Net;
using System.Text;
using System.Windows.Forms;
using MjpegProcessor;
using WebCamClient.Properties;
using ErrorEventArgs = MjpegProcessor.ErrorEventArgs;

namespace WebCamClient
{
	
	public partial class MainForm : Form
	{
		

		/// <summary>
		/// All commands the camera understands
		/// </summary>
		#region Camera Commands

		private const string NightvisionCommand = "IRLed";
		private const string MoveToPresetCommand = "PanTiltPresetPositionMove";
		private const string PanSingleMoveCommand = "PanSingleMoveDegree";
		private const string TiltSingleMoveCommand = "TiltSingleMoveDegree";
		private const string PanTiltSingleMoveCommand = "PanTiltSingleMove";

		#endregion


		/// <summary>
		/// The different URLs used for the camera control
		/// </summary>
		#region CameraUrls

		private static string streamUrl = "http://{0}:{1}@{2}/video.cgi";
		private static string nightvisionUrl = "http://{0}:{1}@{2}/nightmodecontrol.cgi";
		private static string movementUrl = "http://{0}:{1}@{2}/pantiltcontrol.cgi";

		#endregion

		#region Member variables

		private readonly string httpUrl;
		private readonly string host;
		private readonly MjpegDecoder mjpeg;
		private static bool irEnabled = false;
		private bool moveRight = true;
		private Timer t;

		#endregion

		public MainForm()
		{
			InitializeComponent();
			// Initialize the MjpegDecoder
			// All credits go to http://channel9.msdn.com/coding4fun/articles/MJPEG-Decoder
			mjpeg = new MjpegDecoder();
			// Attch the event handlers
			mjpeg.FrameReady += mjpeg_FrameReady;
			mjpeg.Error += _mjpeg_Error;
			
			// We have to make sure that the urls are in the right format
			if (!Settings.Default.url.StartsWith("http://"))
			{
				httpUrl = "http://";
				host = Settings.Default.url;
			}
			httpUrl += Settings.Default.url;
			if (string.IsNullOrEmpty(host))
				host = httpUrl.Replace("http://", string.Empty);
			// and now we are formatting the camera control urls 
			streamUrl = string.Format(streamUrl, Settings.Default.user, Settings.Default.password,
				host);
			nightvisionUrl = string.Format(nightvisionUrl, Settings.Default.user, Settings.Default.password,
				host);
			movementUrl = string.Format(movementUrl, Settings.Default.user, Settings.Default.password,
				host);
		}

		void _mjpeg_Error(object sender, ErrorEventArgs e)
		{
			// If there is an error with the stream, we simply display it
			MessageBox.Show(e.Message);
		}

		private void mjpeg_FrameReady(object sender, FrameReadyEventArgs e)
		{
			// whenever we get a new stream, we have to update the image
			image.Image = e.Bitmap;
		}

		private void Form1_Load(object sender, EventArgs e)
		{
			// during the load we are setting up the stream
			Uri url = new Uri(streamUrl);
			mjpeg.ParseStream(url, Settings.Default.user, Settings.Default.password);
			
		}

		private void button1_Click(object sender, EventArgs e)
		{
			MoveCamera(PanTiltSingleMoveParameters.Up, (int)numPan.Value, (int)numTilt.Value);
		}

		private void SendCommand(string url, string postData)
		{
			// The camera only accepts POST parameters, so we have to get a HttpWebRequest ready	
			ASCIIEncoding encoding = new ASCIIEncoding();
			HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
			byte[] data = encoding.GetBytes(postData);
			// Of course the request needs credentials as well
			req.Credentials = new NetworkCredential(Settings.Default.user, Settings.Default.password);
			req.Method = "POST";
			req.ContentType = "text/html";
			req.ContentLength = data.Length;
			// Create the request stream
			Stream newStream = req.GetRequestStream();
			// Send the data.
			newStream.Write(data, 0, data.Length);
			// Close the stream
			newStream.Close();
			// Send the command
			WebResponse reqp = req.GetResponse();
			// and close the response to get ready for the next command
			reqp.Close();
		}
		/// <summary>
		/// Method to move the camera into a certain direction
		/// </summary>
		/// <param name="direction">The direction to move in</param>
		/// <param name="panValue">The number of degrees to move horizontally</param>
		/// <param name="tiltValue">The number of degrees to move vertically</param>
		private void MoveCamera(PanTiltSingleMoveParameters direction, int panValue, int tiltValue)
		{
			// Lets get the POST-data ready
			string postData = PanSingleMoveCommand + "=" + panValue + "&" + TiltSingleMoveCommand + "=" + tiltValue + "&" +
			                  PanTiltSingleMoveCommand + "=" + (int) direction;
			// And now we send it to the camera
			SendCommand(movementUrl, postData);

		}

		private void button4_Click(object sender, EventArgs e)
		{
			// Make sure the camera is not in Swing-Mode
			if (t != null && t.Enabled) t.Stop();
			// Move the camera in the wanted direction
			MoveCamera(PanTiltSingleMoveParameters.Down, (int)numPan.Value, (int)numTilt.Value);
		}

		private void button2_Click(object sender, EventArgs e)
		{
			// Make sure the camera is not in Swing-Mode
			if (t != null && t.Enabled) t.Stop();
			// Move the camera in the wanted direction
			MoveCamera(PanTiltSingleMoveParameters.Right, (int)numPan.Value, (int)numTilt.Value);
		}

		private void button3_Click(object sender, EventArgs e)
		{
			// Make sure the camera is not in Swing-Mode
			if (t != null && t.Enabled) t.Stop();
			// Move the camera in the wanted direction
			MoveCamera(PanTiltSingleMoveParameters.Left, (int)numPan.Value, (int)numTilt.Value);
		}


		private void button6_Click(object sender, EventArgs e)
		{
			Button btn = ((Button) sender);
			// Check the current status of the IR light
			if (irEnabled)
			{
				// It is enabled, so we need to disable it
				SendCommand(nightvisionUrl, NightvisionCommand+"=0");
				// Set the IR indicator
				irEnabled = false;
				// Update the text on the button
				btn.Text = Resources.EnableIR_ButtonTxt_en;
			}
			else
			{
				// It is disabled, so we need to enable it
				SendCommand(nightvisionUrl, NightvisionCommand + "=1");
				// Set the IR indicator
				irEnabled = true;
				// Update the text on the button
				btn.Text = Resources.DisableIR_ButtonTxt_en;
			}
		}

		// Start swinging :)
		private void button7_Click(object sender, EventArgs e)
		{
			// If the camera is currently swinging, stop it
			if (t != null && t.Enabled) t.Stop();
			// Move the camera all the way to the left
			MoveCamera(PanTiltSingleMoveParameters.Left, 340, 0);
			// Initiate a new timer with a 16 second intervall
			t = new Timer {Interval = 16000};
			// Whenever the timer elapses, do
			t.Tick += (o, args) =>
			{
				// If we are all the way to the left, move right and vice versa
				MoveCamera(moveRight ? PanTiltSingleMoveParameters.Right : PanTiltSingleMoveParameters.Left, 340, 0);
				// Set the direction indicator
				moveRight = !moveRight;
			};
			// Start the timer
			t.Start();
		}

		private void PresetButton_Click(object sender, EventArgs e)
		{

			// Make sure the camera is not in Swing-Mode
			if (t != null && t.Enabled) t.Stop();
			// Move the camera to the selected preset position
			SendCommand(movementUrl, MoveToPresetCommand + "=" + ((Button)sender).Text);
		}

		
		private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
		{
			// Show the settings window
			SettingsWindow win = new SettingsWindow();
			win.ShowDialog();
		}

		private void exitToolStripMenuItem_Click(object sender, EventArgs e)
		{
			// make sure the user really wants to exit
			if(MessageBox.Show(Resources.ExitApp_MsgBoxTxt_en, Resources.ExitApp_MsgBoxTitle_en, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
				Application.Exit();
		}

		private void button5_Click_1(object sender, EventArgs e)
		{

			// Make sure the camera is not in Swing-Mode
			if (t != null && t.Enabled) t.Stop();
			// Move the camera into the home position
			MoveCamera(PanTiltSingleMoveParameters.Home,0,0);
		}

		private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
		{
			// Let's show the About window
			AboutWindow win = new AboutWindow();
			win.ShowDialog();
		}
	}
}
